package com.osdp.gateway.service;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.util.List;

/**
 * 根据服务ID创建路由定义(RouteDefinition)
 * Predicate(谓语) 断言
 */
@Slf4j
@Service
public class GatewayDiscoveryRouteService {

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 初始化断言（谓语）
     * @param serviceId
     * @return
     */
    private List<PredicateDefinition> initPredicate(String serviceId){
        List<PredicateDefinition> definitions = Lists.newArrayList();
        PredicateDefinition predicateDefinition = new PredicateDefinition();
        predicateDefinition.setName(NameUtils.normalizeRoutePredicateName(PathRoutePredicateFactory.class));
        String pattern = "/%s/**";
        predicateDefinition.addArg(RoutePredicateFactory.PATTERN_KEY,String.format(pattern,serviceId));
        definitions.add(predicateDefinition);
        return definitions;
    }

    /**
     *
     * @param serviceId
     * @return
     */
    private List<FilterDefinition> initFilter(String serviceId){
        List<FilterDefinition> definitions = Lists.newArrayList();
        FilterDefinition filterDefinition = new FilterDefinition();
        filterDefinition.setName(NameUtils.normalizeFilterFactoryName(RedirectToGatewayFilterFactory.class));
        String regex = "/%s/(?<remaining>.*)";
        String replacement = "/${remaining}";
        filterDefinition.addArg(RewritePathGatewayFilterFactory.REGEXP_KEY,String.format(regex,serviceId));
        filterDefinition.addArg(RewritePathGatewayFilterFactory.REPLACEMENT_KEY, replacement);
        definitions.add(filterDefinition);
        return definitions;
    }

    /**
     * 根据服务ID创建路由配置信息
     * @param serviceId
     * @return routeDefinition RouteDefinition
     */
    public RouteDefinition initRouteDefinition(String serviceId){
        String uri = String.format("lb://%s",serviceId);
        if(log.isInfoEnabled()){
            log.info("服务uri: "+ uri);
        }
        RouteDefinition routeDefinition = new RouteDefinition();
        routeDefinition.setId(serviceId);
        routeDefinition.setUri(URI.create(uri));
        routeDefinition.setFilters(initFilter(serviceId));
        routeDefinition.setPredicates(initPredicate(serviceId));
        return routeDefinition;
    }
}
